import { AxiosError } from 'axios'
import i18n from '@/i18n'
import { MetaPlatformDao } from '@apps/meta/domain/meta-platform/meta-platform.dao'
import { DomainModel } from '@apps/meta/domain/model'
import { AppLogger, Assist, joinUrl } from '@libs/lhy-common'
import { CoreCacheService, CoreHttpException } from '@libs/lhy-core'
import { HttpService } from '@nestjs/axios'
import { Injectable } from '@nestjs/common'
import { MetaPlatform } from '@prisma/client'
import { MetaPlatformAuthDto } from '../system/meta-platform/dto/meta-platform-auth.dto'
import { MetaPlatformGetBindDataSourceTypeDto } from '../system/meta-platform/dto/meta-platform-get-bind-data-source-type.dto'
import { MetaPlatformGetBindDataSourceDto } from '../system/meta-platform/dto/meta-platform-get-bind-data-source.dto'
import { MetaPlatformGetChartDataDto } from '../system/meta-platform/dto/meta-platform-get-chart-data.dto'
import { MetaPlatformGetHistoryChartDataDto } from '../system/meta-platform/dto/meta-platform-get-history-chart-data.dto'
import { MetaPlatformGetRealtimeDataDto } from '../system/meta-platform/dto/meta-platform-get-realtime-data.dto'
import { MetaPlatformRequestResourceModuleActionDto } from '../system/meta-platform/dto/meta-platform-request-resource-module-action.dto'
import { MetaPlatformSendCommandDto } from '../system/meta-platform/dto/meta-platform-send-comman.dto'
import { MetaPlatformVerifyControlPasswordDto } from '../system/meta-platform/dto/meta-platform-verify-control-password.dto'
import { MetaPlatformWsAuthDto } from '../system/meta-platform/dto/meta-platform-ws-auth.dto'
import { MetaPlatformGetBindDataSourceTypeVo } from '../system/meta-platform/vo/meta-platform-get-bind-data-source-type.vo'
import { MetaPlatformGetBindDataSourceVo } from '../system/meta-platform/vo/meta-platform-get-bind-data-source.vo'
import { MetaPlatformGetChartDataVo } from '../system/meta-platform/vo/meta-platform-get-chart-data.vo'
import { MetaPlatformGetHistoryChartDataVo } from '../system/meta-platform/vo/meta-platform-get-history-chart-data.vo'
import { MetaPlatformGetRealtimeDataVo } from '../system/meta-platform/vo/meta-platform-get-realtime-data.vo'
import { MetaPlatformRequestResourceModuleActionVo } from '../system/meta-platform/vo/meta-platform-request-resource-module-action.vo'
import { MetaPlatformApiException } from './meta-platform-api.exception'

@Injectable()
export class MetaPlatformApiService {
  private readonly logger = new AppLogger(MetaPlatformApiService.name)

  // 平台数据缓存
  private readonly platformCacheService: CoreCacheService

  constructor(
    private readonly platformDao: MetaPlatformDao,
    private readonly httpService: HttpService,
    private readonly cacheService: CoreCacheService
  ) {
    this.platformCacheService = cacheService.createNSService('platform')
  }

  /**
   * 删除平台缓存，重新从数据库获取
   *
   * @param platform
   */
  async refresgPlatform(platform: string) {
    await this.platformCacheService.del(platform)
  }

  /**
   * 清空缓存
   */
  async clear() {
    await this.platformCacheService.clear()
  }

  /**
   * 获取平台数据，有缓存时从缓存读取
   * @param platform
   * @returns
   */
  async getPlatform(platform: string) {
    if (await this.platformCacheService.has(platform)) {
      return await this.platformCacheService.getObj<MetaPlatform>(platform)
    }

    const data = await this.platformDao.getByPlatform(platform)

    Assist.threw(!data, i18n.t('app-meta.meta-platform-api.meta-platform-api.12150112-0', { args: [platform] }))
    await this.platformCacheService.setObj(platform, data)

    return data
  }

  /**
   * 请求资源图表接口
   * @param param
   * @returns
   */
  async requestResourceChart(param: MetaPlatformGetChartDataDto): Promise<MetaPlatformGetChartDataVo> {
    return this.request(
      param.platform,
      platformData =>
        Assist.notNull(
          platformData.resourceChartUrl,
          i18n.t('app-meta.meta-platform-api.meta-platform-api.12150112-1', { args: [platformData.label] })
        ),
      param
    )
  }

  /**
   * 请求资源历史统计图表接口
   * @param param
   * @returns
   */
  async requestResourceHistoryChart(
    param: MetaPlatformGetHistoryChartDataDto
  ): Promise<MetaPlatformGetHistoryChartDataVo> {
    return this.request(
      param.platform,
      platformData =>
        Assist.notNull(
          platformData.resourceHistoryChartUrl,
          i18n.t('meta-platform-api.meta-platform-api.973793-0', { args: [platformData.label] })
        ),
      param
    )
  }

  /**
   * 请求模块动作接口
   * @param param
   * @returns
   */
  async requestResourceModuleAction(
    param: MetaPlatformRequestResourceModuleActionDto
  ): Promise<MetaPlatformRequestResourceModuleActionVo> {
    return this.request(
      param.platform,
      platformData =>
        Assist.notNull(
          platformData.resourceModuleActionUrl,
          i18n.t('app-meta.meta-platform-api.meta-platform-api.12150112-2', { args: [platformData.label] })
        ),
      param
    )
  }

  /**
   * 请求全量实时数据接口
   * @param param
   * @returns
   */
  async requestGetRealtimeData(param: MetaPlatformGetRealtimeDataDto): Promise<MetaPlatformGetRealtimeDataVo> {
    return this.request(
      param.platform,
      platformData =>
        Assist.notNull(
          platformData.getRealtimeDataUrl,
          i18n.t('app-meta.meta-platform-api.meta-platform-api.12150112-3', { args: [platformData.label] })
        ),
      param
    )
  }

  /**
   * 请求token鉴权接口
   * @param param
   * @returns
   */
  async requestAuth(param: MetaPlatformAuthDto): Promise<void> {
    return this.request(
      param.platform,
      platformData =>
        Assist.notNull(
          platformData.authUrl,
          i18n.t('app-meta.meta-platform-api.meta-platform-api.12150112-4', { args: [platformData.label] })
        ),
      param
    )
  }

  /**
   * 请求ws的鉴权接口
   * @param param
   * @returns
   */
  async requestWsAuth(param: MetaPlatformWsAuthDto): Promise<void> {
    return this.request(
      param.platform,
      platformData =>
        Assist.notNull(
          platformData.wsAuthUrl,
          i18n.t('app-meta.meta-platform-api.meta-platform-api.12150112-5', { args: [platformData.label] })
        ),
      param
    )
  }

  /**
   * 请求下发指令接口
   * @param param
   * @returns
   */
  async requestSendCommand(param: MetaPlatformSendCommandDto): Promise<void> {
    return this.request(
      param.platform,
      platformData =>
        Assist.notNull(
          platformData.sendCommandUrl,
          i18n.t('app-meta.meta-platform-api.meta-platform-api.12150112-6', { args: [platformData.label] })
        ),
      param
    )
  }

  /**
   * 校验控制密码接口
   * @param param
   * @returns
   */
  async requestVerifyControlPassword(param: MetaPlatformVerifyControlPasswordDto): Promise<void> {
    return this.request(
      param.platform,
      platformData =>
        Assist.notNull(
          platformData.verifyControlPasswordUrl,
          i18n.t('app-meta.meta-platform-api.meta-platform-api.12150112-7', { args: [platformData.label] })
        ),
      param
    )
  }

  /**
   * 请求获取绑定数据源接口
   * @param param
   * @returns
   */
  async requestGetBindDataSource(param: MetaPlatformGetBindDataSourceDto): Promise<MetaPlatformGetBindDataSourceVo[]> {
    return this.request(
      param.platform,
      platformData =>
        Assist.notNull(
          platformData.getBindDataSourceUrl,
          i18n.t('app-meta.meta-platform-api.meta-platform-api.12150112-8', { args: [platformData.label] })
        ),
      param
    )
  }

  /**
   * 请求获取绑定数据源类型接口
   * @param param
   * @returns
   */
  async requestGetBindDataSourceType(
    param: MetaPlatformGetBindDataSourceTypeDto
  ): Promise<MetaPlatformGetBindDataSourceTypeVo> {
    return this.request(
      param.platform,
      platformData =>
        Assist.notNull(
          platformData.getBindDataSourceTypeUrl,
          i18n.t('app-meta.meta-platform-api.meta-platform-api.12150112-9', { args: [platformData.label] })
        ),
      param
    )
  }

  /**
   * 请求平台接口，包装耗时日志监测
   * @param url
   * @param param
   * @returns
   */
  protected async request<P, R>(
    platform: string,
    relativeUrlGetter: (platformData: DomainModel.MetaPlatform) => string,
    param?: P
  ): Promise<R> {
    const platformData = await this.getPlatform(platform)
    const absoluteUrl = joinUrl(
      Assist.notNull(
        platformData.domainUrl,
        i18n.t('app-meta.meta-platform-api.meta-platform-api.12150112-10', { args: [platformData.label] })
      ),
      relativeUrlGetter(platformData)
    )

    this.logger.info(() =>
      i18n.t('app-meta.meta-platform-api.meta-platform-api.12150112-11', {
        args: [absoluteUrl, JSON.stringify(param ?? '-')],
      })
    )

    const res = await this.logger
      .withPromiseProfile(absoluteUrl, () => this.httpService.axiosRef.post<R>(absoluteUrl, param))
      .catch((e: AxiosError) => {
        if (e instanceof AxiosError && typeof e.response?.data === 'object') {
          const data = e.response.data as MetaPlatformApiException
          throw new CoreHttpException(data.message, { code: data.code, status: e.response.status })
        }

        throw e
      })

    this.logger.info(() =>
      i18n.t('app-meta.meta-platform-api.meta-platform-api.12150112-12', {
        args: [absoluteUrl, JSON.stringify(res.data ?? '-')],
      })
    )
    return res.data
  }
}
